package com.leochan.shuniu.database;

import java.io.File;
import java.util.ArrayList;

import com.leochan.shuniu.database.model.BaseModel;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

public class DatabaseManager {

	public static final int DATABASE_VERSION = 1;

	public static final boolean CHECK_VERSION = true;

	private static final String DATABASE_NAME = "/data/data/com.leochan/app_/data.db";

	private SQLiteDatabase db;

	private static DatabaseManager instance;

	public static DatabaseManager getInstance() {
		if (instance == null) {
			instance = new DatabaseManager();
			instance.initDatabase(DATABASE_NAME);
		}
		return instance;
	}

	public static DatabaseManager createDatabaseManager(Context context,
			String dbPath) {
		DatabaseManager databaseManager = new DatabaseManager(dbPath);
		databaseManager.initDatabase(dbPath);
		return databaseManager;
	}

	private DatabaseManager() {

	}

	private DatabaseManager(String dbPath) {

	}

	private void initDatabase(String dbPath) {
		boolean nodbfile;
		File dbFile = new File(dbPath);
		nodbfile = !dbFile.exists();
		if (nodbfile) {
			File folder = new File(dbFile.getParent());
			if (!folder.exists()) {
				folder.mkdirs();
			}
		}
		db = SQLiteDatabase.openDatabase(dbPath, null,
				SQLiteDatabase.CREATE_IF_NECESSARY);

		if (nodbfile) {
			createTables();
		} else {
			if (CHECK_VERSION) {
				boolean checkFail = true;
				try {
					MonetVersion version = null;
					ArrayList<MonetVersion> versions = new DBVersionDao(db)
							.queryBy(db, "1=1", null);
					if (versions.size() == 1) {
						version = versions.get(0);
					}

					if (version != null
							&& version.getVersion() == DATABASE_VERSION) {
						checkFail = false;
					}
				} catch (Throwable e) {

				}
				if (checkFail) {
					db.close();
					db = null;
					new File(dbPath).delete();
					db = SQLiteDatabase.openDatabase(dbPath, null,
							SQLiteDatabase.CREATE_IF_NECESSARY);
					createTables();
				}
			}
		}
	}

	private void createTables() {
		try {
			db.beginTransaction();
			new DBVersionDao(db).createTable();
			db.setTransactionSuccessful();
		} finally {
			db.endTransaction();
		}
	}

	public SQLiteDatabase getDatabase() {
		return db;
	}

	public String getDatabasePath() {
		return db.getPath();
	}

	public static void close() {
		if (instance != null) {
			SQLiteDatabase database = instance.db;
			if (database != null && database.isOpen()) {
				database.close();
			}
			instance = null;
		}
	}

	@Override
	protected void finalize() throws Throwable {
		if (db != null) {
			db.close();
			db = null;
		}
		super.finalize();
	}

	private static class MonetVersion extends BaseModel {

		private static final long serialVersionUID = -1763312771593929974L;

		private int version;

		public MonetVersion() {
			super();
		}

		public MonetVersion(int version) {
			super();
			this.version = version;
		}

		public int getVersion() {
			return version;
		}

		public void setVersion(int version) {
			this.version = version;
		}

	}

	private static class DBVersionDao extends BaseDao<MonetVersion> {

		public DBVersionDao(SQLiteDatabase db) {
			super(db);
		}

		@Override
		protected String createTableSql() {
			return "create table db_version (_id integer primay key autoincreament, version integer)";
		}

		@Override
		protected String getTableName() {
			return "db_version";
		}

		@Override
		protected void initData() {
			saveOrUpdate(db, new MonetVersion(DATABASE_VERSION));
		}

		@Override
		protected MonetVersion cursor2Model(Cursor cursor) {
			MonetVersion mv = new MonetVersion();

			int index = cursor.getColumnIndex(getKeyName());
			mv.setId(cursor.getLong(index));

			index = cursor.getColumnIndex("version");
			mv.setVersion(cursor.getInt(index));

			return mv;
		}

		@Override
		protected ContentValues model2ContentValues(MonetVersion model) {
			ContentValues cv = new ContentValues();
			cv.put("version", model.getVersion());
			return cv;
		}

		@Override
		protected Object getWriteLock() {
			return DBVersionDao.class;
		}

	}
}
